package org.example.sec06;

import com.seaway.models.sec06.*;
import io.grpc.stub.StreamObserver;
import org.example.sec08.respository.AccountRespository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

/**
 * @author Administrator
 */
public class TransferService extends TransferServiceGrpc.TransferServiceImplBase {
    private static final Logger LOG = LoggerFactory.getLogger(TransferService.class);
    private static int count = 0;

    @Override
    public StreamObserver<TransferRequest> transfer(StreamObserver<TransferResponse> responseObserver) {
        return new StreamObserver<TransferRequest>() {

            @Override
            public void onNext(TransferRequest transferRequest) {

                TransferStatus transfer = this.transfer(transferRequest);

                var resp = TransferResponse.newBuilder()
                        .setFromAccount(this.toAccountBalance(transferRequest.getFromAccount()))
                        .setToAccount(this.toAccountBalance(transferRequest.getToAccount()))
                        .setStatus(transfer)
                        .build();

                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                count++;
                LOG.info("======================= server receive data is :count is : {}, {}", count, transferRequest);

                responseObserver.onNext(resp);

            }

            @Override
            public void onError(Throwable throwable) {
                LOG.error("client error {}", throwable.getMessage());
            }

            @Override
            public void onCompleted() {
                LOG.info("transfer request stream completed...");
                responseObserver.onCompleted();
            }

            private TransferStatus transfer(TransferRequest request) {
                int amount = request.getAmount();
                var status = TransferStatus.REJECTED;
                int fromAccount = request.getFromAccount();
                int toAccount = request.getToAccount();
                if (AccountRespository.getBalance(fromAccount) >= amount && (fromAccount != toAccount)) {
                    AccountRespository.deductAccount(fromAccount, amount);
                    AccountRespository.addAmount(toAccount, amount);
                    status = TransferStatus.COMPLETED;
                }
                return status;
            }

            private AccountBalance toAccountBalance(int account) {
                return AccountBalance.newBuilder()
                        .setAccountNumber(account)
                        .setBalance(AccountRespository.getBalance(account))
                        .build();
            }
        };
    }
}
